home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / xmodem.arc / XMDM1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-06-15  |  10.9 KB  |  414 lines

  1. /*----------------------------------------------------------------
  2.                             XMODEM.C
  3.                           Main Drivers
  4.              (c) Copyright 1985 By Donald G Krantz
  5.                       All Rights Reserved
  6. ----------------------------------------------------------------*/
  7.  
  8. #define MAIN
  9. #include "stdio.h"
  10. #include "b:xmodem.h"
  11.  
  12. char *c_tx, *c_rx, *c_txstat, *c_rxstat, *c_abort;
  13. int _tx(), _rx(), _txstat(), _rxstat(), _abort(), _lcon();
  14.  
  15. /*----------------------------------------------------------------
  16. main() XMODEM main driver
  17. ----------------------------------------------------------------*/
  18. VOID main( argc, argv )
  19.    int argc;
  20.    char *argv[];
  21. {
  22.    int i;
  23.     init();
  24.     printf( "XMODEM 5.0 - Osborne 1/BYE-Z -  D. Krantz" );
  25.     parsopt( &argc, argv );
  26.         if( !option_speced || (t_r_mode == 0) || (argc < 2) )
  27.         do_usage();
  28.     printf( "\n%s mode, batch %s", crc ? "CRC" : "Checksum",
  29.         batch_request ? "ON" : "OFF" );
  30.     if( t_r_mode == 'S' )
  31.         for( i=1 ; i < argc ; i++ )
  32.             show_size( argv[ i ] );
  33.     else
  34.         if( batch_request )
  35.             make_rxspec( argc, argv );
  36.     printf( "\n\n* * * * Send ^X to cancel * * * *" );
  37.     printf( "\nReady to start transfer" );
  38.     if( t_r_mode == 'R' )
  39.         rx_exec( argc, argv );
  40.     else
  41.         tx_exec( argc, argv );
  42. }
  43.  
  44. /*---------------------------------------------------------------
  45. error() does error abort cleanup
  46.  
  47. References globals: fd;
  48. ---------------------------------------------------------------*/
  49. VOID error( str )
  50.    char *str;
  51. {
  52.     tx( CAN );            /* alert remote        */
  53.     sprintf( msg, "\n\nError - %s\n", str );
  54.     lcl_str( msg );
  55.     printf( msg );
  56.     exit( 1 );        
  57. }
  58.  
  59. /*----------------------------------------------------------------
  60. abort() checks for carrier.
  61. ----------------------------------------------------------------*/
  62. VOID abort()
  63. {
  64.     if( !ret_a( c_abort, 0,0,0,0 ) )
  65.         exit( 1 );
  66. }
  67.  
  68. /*----------------------------------------------------------------
  69. rx() gets a char from the remote system.
  70. ----------------------------------------------------------------*/
  71. char rx() { return( ret_a( c_rx,0,0,0,0 ) ); }
  72.  
  73. /*----------------------------------------------------------------
  74. rxstat() returns TRUE if a char is awaiting input.
  75. ----------------------------------------------------------------*/
  76. rxstat() { abort(); return( ret_a( c_rxstat,0,0,0,0 ) ); }
  77.  
  78. /*----------------------------------------------------------------
  79. tx() sends a char to remote and updates the CRC buffer.
  80. ----------------------------------------------------------------*/
  81. VOID tx( ch )
  82. {
  83.    int i;
  84.     for( i=0 ; i < 1000; i++ )
  85.     {
  86.         if( txstat() )
  87.         {
  88.             ret_a( c_tx, ch, 0,0,0 );
  89.             updcrc( ch );
  90.             return;
  91.         }
  92.     }
  93.     error( "Transmitter timed out" );
  94. }
  95.  
  96. /*----------------------------------------------------------------
  97. txstat() returns TRUE if tx register is empty.
  98. ----------------------------------------------------------------*/
  99. txstat() { abort(); return( ret_a( c_txstat, 0,0,0,0 ) ); }
  100.  
  101. /*----------------------------------------------------------------
  102. init() moves Osborne code out into the heap where it can
  103. operate safely.
  104. ----------------------------------------------------------------*/
  105. init()
  106. {
  107.     c_tx = alloc( 11 );
  108.     c_rx = alloc( 11 );
  109.     c_txstat = alloc( 11 );
  110.     c_rxstat = alloc( 11 );
  111.     c_abort = alloc( 15 );
  112.     movmem( (char *)_tx, c_tx, 11 );
  113.     movmem( (char *)_rx, c_rx, 11 );
  114.     movmem( (char *)_txstat, c_txstat, 13 );
  115.     movmem( (char *)_rxstat, c_rxstat, 13 );
  116.     movmem( (char *)_abort, c_abort, 15 );
  117. }
  118.  
  119. /*----------------------------------------------------------------
  120. movmem() transfers blocks of memory.
  121. ----------------------------------------------------------------*/
  122. movmem( source, dest, count )
  123.    char *source, *dest;
  124.    int count;
  125. {
  126.    register int i;
  127.     for( i=0 ; i<count ; i++ )
  128.         *(dest++) = *(source++);
  129. }
  130.  
  131. /*----------------------------------------------------------------
  132. lcl_char() outputs a char to the local console.
  133. ----------------------------------------------------------------*/
  134. VOID lcl_char( ch )
  135.    char ch;
  136. {
  137.     ret_a( _lcon, 0, ch, 0, 0 );
  138. }
  139.  
  140. #if LOG_ON
  141. /*----------------------------------------------------------------
  142. log_xfr() logs uploads and downloads
  143. ----------------------------------------------------------------*/
  144. VOID log_xfr( name, mode, logfile )
  145.    char *name, *mode;
  146. {
  147.    FILE *fp;
  148.  
  149.     if( (fp=fopen( logfile, "r" )) == NULL )
  150.     {
  151.         fp = fopen( logfile, "w" );
  152.         if( fp )
  153.         {
  154.             fprintf( fp, "XMODEM File Transfer Log\n" );
  155.             fclose( fp );
  156.         }
  157.     }
  158.     else
  159.         fclose( fp );
  160.     fp = fopen( logfile, "a" );
  161.     fprintf( fp, "%-15s : %8s : %d/%d/%d\n", 
  162.        name, mode, month(), day(), year() );
  163.     fclose( fp );
  164. }
  165.  
  166. month()
  167. { return( *((char *)0xEF64) ); }
  168.  
  169. day()
  170. { return( *((char *)0xEF63) ); }
  171.  
  172. year()
  173. { return( *((char *)0xEF65) ); }
  174.  
  175. #endif
  176. /*----------------------------------------------------------------
  177. rx_exec() receive mode executive driver
  178. ----------------------------------------------------------------*/
  179. rx_exec( argc, argv )
  180.    int argc;
  181.    char *argv[];
  182. {
  183.    char fcb[ NAMESIZE + 1 ];    /* used by unparse()        */
  184.    char name[ NAMESIZE + 5];    /* unparsed name        */
  185.  
  186.     if( batch_request )
  187.         while( TRUE )
  188.         {
  189.             while( rxstat() )
  190.                 rx();
  191.             rxname( fcb );
  192.             unparse( name, fcb );
  193.             sprintf( msg, "\nReceiving: %s\n", name );
  194.             lcl_str( msg );
  195.             rxfile( make( name ) );
  196. #if LOG_ON
  197.             log_xfr( name, "UPLOAD", UPLOG );
  198. #endif
  199.         }
  200.     else
  201.     {
  202.         rxfile( make( argv[ 1 ] ) );
  203. #if LOG_ON
  204.         log_xfr( argv[ 1 ], "UPLOAD", UPLOG );
  205. #endif
  206.     }
  207. }
  208.  
  209. /*----------------------------------------------------------------
  210. tx_exec() transmit mode executive driver.
  211. ----------------------------------------------------------------*/
  212. tx_exec( argc, argv )
  213.    int argc;
  214.    char *argv[];
  215. {
  216.    int i;
  217.     if( batch_request )
  218.     {
  219.         for( i=1 ; i<argc ; i++ )
  220.         {
  221.             fd = fopen( argv[ i ], "rb" );
  222.             sprintf( msg, "\nSending: %s\n", argv[ i ] );
  223.             lcl_str( msg );
  224.             txname( parse( argv[ i ], scr_name ) );
  225.             txfile( fd );
  226. #if LOG_ON
  227.             log_xfr( argv[ i ], "DOWNLOAD", DOWNLOG );
  228. #endif
  229.         }
  230.         while( 
  231.             wait( 10, TRUE, TRUE ) != NAK )
  232.             ;
  233.         tx( ACK );
  234.         sleep();
  235.         tx( EOT );
  236.     }
  237.     else
  238.     {
  239.         fd = fopen( argv[ 1 ], "rb" );
  240.         txfile( fd );
  241. #if LOG_ON
  242.         log_xfr( argv[ 1 ], "DOWNLOAD", DOWNLOG );
  243. #endif
  244.     }
  245. }
  246.  
  247. /*----------------------------------------------------------------
  248. parsopt() parses the command line options and extracts all
  249. "dash" options from the command line argument list.
  250. ----------------------------------------------------------------*/
  251. VOID parsopt( argc, argv )
  252.    int *argc;
  253.    char  *argv[];
  254. {
  255.    int i, j;
  256.    
  257.    batch_request = FALSE;
  258.    crc = TRUE;
  259.    t_r_mode = 0;
  260.    for( i = 1 ; i < *argc ; i++ )
  261.    {
  262.       if( *argv[ i ] == '-' )
  263.       {
  264.          option_speced = TRUE;
  265.          switch( *(argv[ i ] + 1) )
  266.          {
  267.             case 'R':
  268.                if( t_r_mode != 0 )
  269.                {
  270.                   sprintf( msg, "Ambiguous Option: %s", argv[ i ] );
  271.                   error( msg );
  272.                }
  273.                t_r_mode = 'R';
  274.                break;
  275.             case 'S':
  276.                if( t_r_mode != 0 )
  277.                {
  278.                   sprintf( "Ambiguous Option: %s", argv[ i ] );
  279.                   error( msg );
  280.                }
  281.                t_r_mode = 'S';
  282.                break;
  283.             case 'B':
  284.         batch_request = TRUE;
  285.         break;
  286.             case 'C':
  287.                crc = FALSE;
  288.                break;
  289.             default:
  290.                sprintf( msg, "Unrecognised option: %s", argv[ i ] );
  291.                error( msg );
  292.          }
  293.          for( j = i ; j < *argc ; j++ )
  294.             argv[ j ] = argv[ j + 1 ];
  295.          (*argc)--;
  296.          i--;
  297.       }
  298.    }
  299. }
  300.  
  301. /*----------------------------------------------------------------
  302. do_usage() prints use instructions and then exits.
  303. ----------------------------------------------------------------*/
  304. VOID do_usage()
  305. {
  306.     printf( "\n** This XMODEM probably doesn't work like you think **\n\n" );
  307.     printf( "Usage is:     XMODEM {option list} {filespec}\n\n" );
  308.     printf( "Options are:  -Recieve  -Send  -Batch  -Checksum\n\n" );
  309.     printf( "Examples:     XMODEM -S ANYFILE.NAM\n" );
  310.     printf( "              XMODEM -S -B C:ANYDOC A:LU.DOC\n" );
  311.     printf( "              XMODEM -R ARTICLE.NSL\n" );
  312.     printf( "              XMODEM -R -B -C D:\n\n" );
  313.     printf( "* \"Send\" means BeeB sends TO YOU\n" );
  314.     printf( "* \"Receive\" means YOU send TO BeeB\n" );
  315.     printf( "* Wildcards not allowed for \"filespec\"\n" );
  316.     printf( "* for -R option in BATCH mode, use drivespec ONLY." );
  317.     exit( 1 );
  318. }
  319.  
  320. /*----------------------------------------------------------------
  321. show_size() prints the size (in records) of a file.
  322. ----------------------------------------------------------------*/
  323. VOID show_size( str )
  324.    char *str;
  325. {
  326.     if( index( str, '.' ) != NULL )
  327.         if( strncmp( index( str, '.' ), ".COM" ) == 0 )
  328.             error( "\n?  Hey, what's this? I don't do .COM files!" );
  329.     if( (fd = fopen( str, "rb" )) == NULL )
  330.     {
  331.         sprintf( msg,"\nAborting - can't open %s", str );
  332.         error( msg );
  333.     }
  334.     printf( "\n%-14s - size = %04d records", str, 
  335.               (int)(fseek( fd, 0, 2 )/128 ));
  336.     fclose( fd );
  337. }
  338.  
  339. /*----------------------------------------------------------------
  340. make() opens a file for reception. make() changes .COM files to
  341.  .OBJ files, and ensures that unique names are used. Returns the
  342. FILE pointer to the open file.
  343. ----------------------------------------------------------------*/
  344. FILE *make( name )
  345.    char *name;
  346. {
  347.    char fullname[ 20 ];
  348.    int i;
  349.    FILE *fp;
  350.  
  351.     if( strncmp( index( name, '.' ), ".COM", 4 ) == 0 )
  352.         strcpy( index( name, '.' ), ".OBJ" );
  353.     strcpy( fullname, rx_spec );
  354.     strcat( fullname, name );
  355.     for( i = 0 ; i < 10 ; i++ )
  356.     {
  357.         if( (fp=fopen( fullname, "r" )) == NULL )
  358.         {
  359.             if( (fp=fopen( fullname, "wb" )) == NULL )
  360.             {
  361.                 sprintf( msg,"\nAborting - can't create %s",fullname);
  362.                 error( msg );
  363.             }
  364.             return( fp );
  365.         }
  366.         fullname[ strlen( fullname ) - 1 ] = i + '1';
  367.         fclose( fp );
  368.     }
  369.     sprintf( msg, "\nAborting - can't open %s", fullname );
  370.     error( msg );
  371. }
  372.  
  373. /*----------------------------------------------------------------
  374. lcl_str outputs a string to the local console.
  375. ----------------------------------------------------------------*/
  376. VOID lcl_str( str )
  377.    char *str;
  378. {
  379.     while( *str != '\0' )
  380.     {
  381.         if( *str == '\n' )
  382.             lcl_char( '\r' );
  383.         lcl_char( *str );
  384.         str++;
  385.     }
  386. }    
  387.  
  388. VOID make_rcxspec( argc, argv )
  389.    int argc;
  390.    char *argv[];
  391. {
  392.     if( !batch_request )
  393.         if( argc == 2 )
  394.             return;
  395.     if( argc == 1 )
  396.     {
  397.         rx_spec[ 0 ] = '\0';
  398.         return;
  399.     }
  400.     if( argc == 2 )
  401.         if( (strlen( argv[ 1 ]) == 2) && ( *(argv[1]+1) == ':'))
  402.         {
  403.             strcpy( rx_spec, argv[ 1 ] );
  404.             return;
  405.         }
  406.     printf( "\nAborting - improper receive filespec" );
  407.     do_usage();
  408. }
  409.  
  410. {
  411.             strcpy( rx_spec, argv[ 1 ] );
  412.             return;
  413.         }
  414.     printf( "\nAborting - improper receive files